/*
 *	entrypoint.c 
 *	© 2009 DigiFi Limited
 *
 *	Entry point into the test harness for the libdigifi library
 *
 */


#include "regex.h"

#include "../headers/dfclient.h"
#include "../headers/dfregex.h"
#include "../headers/dfregexcache.h"

#include "./util/stringconcat.h"
#include "./util/stringext.h"

// test struct for cache test
struct df_cacheteststruct {
	char* value;
	int ivalue;
};


// async functions
static void print_gettrackname(df_track *tr);
static void print_albumartist(df_albumartist *aa);
static void print_time(df_time *t);
static void print_int(int i);
static void print_string(char *s);
static void print_trackname(df_trackname *tn);
static void print_detailedtrack(df_detailedtrack *dt);
static void print_checkcoverimage(char *name, char *uri);

static void print_artistrow(df_rows *info, df_artistrow *ar);
static void print_roomrow(df_rows *info, df_roomrow *rr);
static void print_trackrow(df_rows *info, df_trackrow *tr); 
static void print_albumrow(df_rows *info, df_albumrow *ar);
static void print_albumdetailrow(df_rows *info, df_albumdetailrow *ar);
static void print_subgenrerow(df_rows *info, df_subgenrerow *sgr);
static void print_keyvaluerow(df_rows *info, df_keyvaluerow *kvr);
static void print_genrerow(df_rows *info, df_genrerow *gr);
static void print_trackinforow(df_rows *info, df_trackinforow  *tir);

static void menu_processGet(void);
static void menu_processSet(void);
static void menu_processRGet(void);
static void menu_processRow(void);
static void menu_processTest(void);
static void menu_processDump(void);
static void menu_processQuery(void);
static void menu_processFree(void);

static void help_menu(void);
static int findCommand(char* list[], char *key, int length);

static void cache_test(void);
static void regex_test(void);
static void concat_test(void);
static void thread_test(void);
static void stringext_test(void);

static void cache_query(void);

static void error_callback(int num, char *message);
static void debug_callback(char *message);

static void connect_callback(int err);
static void discover_callback(df_server *servers);


static int num_menuItems = 20;
static char *menuItems[20] = {
	"discover",
	"connect",
	"disconnect",
	"changeroom",
	"play",
	"stop",
	"pause",
	"next",
	"prev",
	"clear",
	"get",
	"set",
	"rget",
	"row",
	"test",
	"dump",
	"query",
	"free",
	"help",
	"quit"};
	
static int num_setItems = 3;
static char *setItems[3] = {
	"volume",
	"shuffle",
	"repeat"};
	
static int num_getItems = 10;
static char *getItems[10] = {
	"volume",
	"repeat",
	"shuffle",
	"playerstatus",
	"trackname",
	"tracknum",
	"trackpos",
	"albumartist",
	"checkcoverimage",
	"librarychecksum"};
	
static int num_rgetItems = 10;
static char *rgetItems[10] = {
	"albumartist",
	"detailedtrackinfo",
	"lastplayererror",
	"playerstatus",
	"playingchecksum",
	"repeat",
	"shuffle",
	"trackname",
	"trackposition",
	"clear"};
	
static int num_rowItems = 20;
static char *rowItems[20] = {
	"artists",
	"albums",
	"albumsforartists",
	"playlistsforsubgenre",
	"userplaylists",
	"tracks",
	"tracksforplaylist",
	"genres",
	"subgenresforgenre",
	"extcontributors",
	"extalbumsbycontributor",
	"albumsotherinfo",
	"extalbumcredits",
	"tracksotherinfo",
	"exttrackcontributors",
	"exttracksbycontributors",
	"albumdetails",
	"rooms",
	"advancedstatus",
	"currentplaylist"};

static int num_testItems = 5;
static char *testItems[5] = {
	"cache",
	"thread",
	"concat",
	"regex",
	"stringext"};
	
static int num_dumpItems = 5;
static char *dumpItems[5] = {
	"cache",
	"msg_threads",
	"msg_thread_buffer",
	"rget_threads",
	"rget_buffer"};
	
static int num_queryItems = 1;
static char *queryItems[1] = {
	"cache"};
	
static int num_freeItems = 2;
static char *freeItems[2] = {
	"cache",
	"rget_buffer"};
	
static unsigned int room_id = 1;


int main(int argc, char *argv[]) {
	
	int i = 0;	
	char input[20];
	
	// hookup callbacks
	dferrors_register_errorcallback(error_callback);
	dferrors_register_debugcallback(debug_callback);
	
	printf("/////////////////////////////////////////////////////////////////\n");
	printf("//   libdigifi test application                                //\n");
	printf("/////////////////////////////////////////////////////////////////\n");
	printf("Machine IP: %s\n", dfsocket_getlocalip());
	
	while (1) {
		printf("> ");
		scanf("%s", input);
		
		switch (findCommand(menuItems,input,num_menuItems)) {
			
			case 0:					// discover
				df_discover(15, discover_callback);
				printf("It will take around 15 seconds to discover DigiFis.\n");
			break;
		
			case 1:					// connect
				printf("Enter the ip address: ");
				scanf("%s", input);
				i = df_connect(input,5, connect_callback);
			break;
			
			case 2:					// disconnect
				df_disconnect();
				printf("Disconnected.\n");
			break;
			
			case 3:					// changeroom
				printf("Enter the room id: ");
				scanf("%u", &room_id);
				printf("Room changed.\n");
			break;
			
			case 4:					// play
			dfvoid_play(room_id);
			//dfvoid_playalbum(room_id, 0, "a4376", 1);
			//dfvoid_playtrack(room_id, 0, "a75336");
			break;
			
			case 5:					// stop
			dfvoid_stop(room_id);
			break;
			
			case 6:					// pause
			dfvoid_pause(room_id);
			break;
			
			case 7:					// next
			dfvoid_next(room_id);
			break;
			
			case 8:					// prev
			dfvoid_previous(room_id);
			break;
			
			case 9:					// clear
			dfvoid_clearplaylist(room_id);
			break;
			
			case 10:					// get
				menu_processGet();
			break;
			
			case 11:					// set
				menu_processSet();
			break;
			
			case 12:				// rget
			menu_processRGet();
			break;
			
			case 13:				// row
			menu_processRow();
			break;
			
			case 14:				// test
			menu_processTest();
			break;
			
			case 15:				// dump
			menu_processDump();
			break;
			
			case 16:				// query
			menu_processQuery();
			break;
			
			case 17:				// free
			menu_processFree();
			break;
		
			case 18:					// help
			help_menu();
			break;
			
			case 19:				// quit
			return 0;
		
			default:
			printf("Unknown command, type 'help all' for options.\n");
			break;
			
		}
	}
	
	return 0;
	
}


static void menu_processGet(void) {
	char input[20];
	
	scanf("%s", input);
	
	switch(findCommand(getItems,input,num_getItems)) {
		case 0:						// volume
		dfget_volume(room_id, print_int);
		break;
		case 1:						// repeat
		dfget_repeat(room_id, print_int);
		break;
		case 2:						// shuffle
		dfget_shuffle(room_id, print_int);
		break;
		case 3:						// playerstatus
		dfget_playerstatus(room_id, print_string);
		break;
		case 4:						// trackname
		dfget_trackname(room_id, print_gettrackname);
		break;
		case 5:						// tracknum
		dfget_tracknum(room_id, print_int);
		break;
		case 6:						// trackpos
		dfget_trackpos(room_id, print_time);
		break;
		case 7:						// albumartist
		dfget_albumartist(room_id, print_albumartist);
		break;
		case 8:						// checkcoverimage
		printf("Track Address: ");
		scanf("%s", input);
		dfget_checkcoverimage(input, 3, 2, 0, "HTTP", "BMP", print_checkcoverimage);
		break;
		case 9:
		dfget_librarychecksum(room_id, print_int);
		default:
		printf("Unknown get command, type 'help get' for options.\n");
		break;
	}
}

static void menu_processSet(void) {
	char input[20];
	int i;
	
	scanf("%s", input);
	
	switch(findCommand(setItems,input,num_setItems)) {
		case 0:						// volume
		printf("Volume (0-255): ");
		scanf("%d", &i);
		dfset_volume(room_id, i);
		break;
		case 1:						// shuffle
		printf("Shuffle (0-1): ");
		scanf("%d", &i);
		dfset_shuffle(room_id, i);
		break;
		case 2:						// repeat
		printf("Repeat (0-1): ");
		scanf("%d", &i);
		dfset_repeat(room_id, i);
		break;
		default:
		printf("Unknown set command, type 'help set' for options.\n");
		break;
	}
}

static void menu_processRGet(void) {
	char input[20];
	
	scanf("%s", input);
	
	switch(findCommand(rgetItems,input,num_rgetItems)) {
		case 0:						// albumartist
		dfrget_albumartist(room_id, print_albumartist);
		break;
		case 1:						// detailedtrackinfo
		dfrget_detailedtrackinfo(room_id, print_detailedtrack);
		break;
		case 2:						// lastplayererror
		dfrget_lastplayererror(room_id, print_string);
		break;
		case 3:						// playerstatus
		dfrget_playerstatus(room_id, print_string);
		break;
		case 4:						// playingchecksum
		dfrget_playingchecksum(room_id, print_string);
		break;
		case 5:						// repeat
		dfrget_repeat(room_id, print_int);
		break;
		case 6:						// shuffle
		dfrget_shuffle(room_id, print_int);
		break;
		case 7:						// trackname
		dfrget_trackname(room_id, print_trackname);
		break;
		case 8:						// trackposition
		dfrget_trackposition(room_id, print_time);
		break;
		case 9:						// clear
		dfrget_clearcommands(room_id);
		break;
		case 10:					// bufferflush
		dfrget_bufferflush();
		break;
		case 11:					// bufferdump
		dfrget_bufferdump();
		break;
		default:
		printf("Unknown rget command, type 'help rget' for options.\n");
		break;
	}
}

static void menu_processRow(void) {
	char input[20], album[20];
	
	scanf("%s", input);
	
	switch(findCommand(rowItems,input,num_rowItems)) {
		case 0:								// artists
		dfrow_artists(0, print_artistrow);
		break;
		
		case 1:								// albums
		dfrow_albums("","",print_albumrow);
		break;
		
		case 2:								// albumsforartists
		printf("Address: ");
		scanf("%s", input);
		dfrow_albumsforartists(input, "", "", print_albumrow);
		break;
		
		case 3:								// playlistsforsubgenre
		printf("Address: ");
		scanf("%s", input);
		dfrow_playlistsforsubgenre(input,"","", print_albumrow);
		break;
			
		case 4:								// userplaylists
		dfrow_userplaylists("", "", print_albumrow);
		break;
		
		case 5:								// tracks
		dfrow_tracks(print_trackrow);
		break;
		
		case 6:								// tracksforplaylist
		printf("Address: ");
		scanf("%s", input);
		dfrow_tracksforplaylist(input, print_trackrow);
		break;
		
		case 7:								// genres
		dfrow_genres(0, "", "", print_genrerow);
		break;
		
		case 8:								// subgenresforgenre
		printf("Address: ");
		scanf("%s", input);
		dfrow_subgenresforgenre(input, 0, "" , "", print_subgenrerow);
		break;
		
		case 9:								// extcontributors
		break;
		
		case 10:							// extalbumsbycontributor
		break;

		case 11:							// albumsotherinfo
		break;
		
		case 12:							// extalbumcredits
		break;

		case 13:							// tracksotherinfo
		printf("Address: ");
		scanf("%s", input);
		dfrow_tracksotherinfo(input, print_trackinforow);
		break;
		
		case 14:							// exttrackcontributors
		break;
		
		case 15:							// exttracksbycontributor
		printf("Address: ");
		scanf("%s", input);
		printf("Album: ");
		scanf("%s", album);
		dfrow_exttracksbycontributor(input, 0, album, print_trackrow);
		break;
		
		case 16:
		printf("Address: ");
		scanf("%s", input);
		dfrow_albumdetails(input, print_albumdetailrow);
		break;
		
		case 17:							// rooms
		dfrow_rooms(0, print_roomrow);
		break;
		
		case 18:							// advancedstatus
		dfrow_advancedstatus(print_keyvaluerow);
		break;
		
		case 19:							// currentplaylist
		dfrow_currentplaylist(room_id, print_trackrow);
		break;
		
		default:
		printf("Unknown row command, type 'help row' for options.\n");
		break;
	}
}

static void menu_processTest(void) {
	char input[20];
	
	scanf("%s", input);
	
	switch(findCommand(testItems,input,num_testItems)) {
		case 0:								// cache
		cache_test();
		break;
		case 1:								// thread
		thread_test();
		break;
		case 2:								// concat
		concat_test();
		break;
		case 3:								// regex
		regex_test();
		break;
		case 4:								// stringext
		stringext_test();
		break;
		default:
		printf("Unknown row command, type 'help test' for options.\n");
		break;
	}
}

static void menu_processDump(void) {
	char input[20];
	int i;
	
	scanf("%s", input);
	
	switch(findCommand(dumpItems,input,num_dumpItems)) {
		case 0:										// cache
		dfregexcache_dump();
		break;
		case 1:										// msg_threads
		dfmultithread_dump();
		break;
		case 2:										// msg_thread_buffer
		printf("Thread id: ");
		scanf("%d", &i);
		dfmultithread_dumpbuffer(i);
		break;
		case 3:										// rget_threads
		dfrget_dump();
		break;
		case 4:										// rget_buffer
		dfrget_bufferdump();
		break;
		default:
		printf("Unknown row command, type 'help dump' for options.\n");
		break;
	}
}

static void menu_processQuery(void) {
	char input[20];
	
	scanf("%s", input);
	
	switch(findCommand(queryItems,input,num_queryItems)) {
		case 0:										// cache
		cache_query();
		break;
		default:
		printf("Unknown row command, type 'help query' for options.\n");
		break;
	}
}

static void menu_processFree(void) {
	char input[20];
	
	scanf("%s", input);
	
	switch(findCommand(freeItems,input,num_freeItems)) {
		case 0:										// cache
		dfregexcache_free();
		break;
		case 1:										// rget_buffer
		dfrget_bufferflush();
		break;
		default:
		printf("Unknown row command, type 'help free' for options.\n");
		break;
	}
}

static void help_menu(void) {
	char buffer[6];
	int i;
	
	scanf("%s",buffer);
	
	printf("Commands:\n");
	if (strcmp(buffer, "all") == 0) {
		for (i=0; i<num_menuItems; i++) {
			printf("%s\n", menuItems[i]);
		}
	}
	else if (strcmp(buffer, "get") == 0) {
		for (i=0; i<num_getItems; i++) {
			printf("%s\n", getItems[i]);
		}
	}
	else if (strcmp(buffer, "set") == 0) {
		for (i=0; i<num_setItems; i++) {
			printf("%s\n", setItems[i]);
		}
	}
	else if (strcmp(buffer, "rget") == 0) {
		for (i=0; i<num_rgetItems; i++) {
			printf("%s\n", rgetItems[i]);
		}
	}
	else if (strcmp(buffer, "row") == 0) {
		for (i=0; i<num_rowItems; i++) {
			printf("%s\n", rowItems[i]);
		}
	}
	else if (strcmp(buffer, "test") == 0) {
		for (i=0; i<num_testItems; i++) {
			printf("%s\n", testItems[i]);
		}
	}
	else if (strcmp(buffer, "dump") == 0) {
		for (i=0; i<num_dumpItems; i++) {
			printf("%s\n", dumpItems[i]);
		}
	}
	else if (strcmp(buffer, "query") == 0) {
		for (i=0; i<num_queryItems; i++) {
			printf("%s\n", queryItems[i]);
		}
	}
	else if (strcmp(buffer, "free") == 0) {
		for (i=0; i<num_freeItems; i++) {
			printf("%s\n", freeItems[i]);
		}
	}
	else { 
		printf("Unknown help command. Avaliable are all, get, set, rget, row, test, dump, query and free.\n");
	}
	printf("\n");
	
	
	
	
}


static int findCommand(char* list[], char *key, int length) {

	int i;

	for (i=0; i<length; i++) {

		if (strcmp(list[i],key) == 0)
			return i;
	}
	
	return -1;
	
}


static void cache_query(void) {
	char key[20];
	regex_t *ret;
	
	scanf("%s", key);
	
	dfregexcache_get(key, (void*)&ret);
	
	dferrors_printdebug("res: %d\n", ret->re_nsub);
	
}




static void regex_test(void) {
	char *string;
	dfrx_result *rx;
	
	string = "[ACK GetShuffle 1 1]";
	
	rx = dfregex_match(string, "void", DF_VOID_COMMAND);
	
	printf("%s\n", (rx!=NULL)?rx->value:"(null)");
}


static void concat_test(void) {
	// do a string concat test
	int id;
	
	id = sc_start();
	
	if (sc_add(id, "Hello ") < 0) { printf("failed.\n"); }
	sc_dump(id);
	if (sc_add(id, "my ") < 0) { printf("failed.\n"); }
	sc_dump(id);
	if (sc_add(id, "name ") < 0) { printf("failed.\n"); }
	sc_dump(id);
	if (sc_add(id, "is ") < 0) { printf("failed.\n"); }
	sc_dump(id);
	if (sc_add(id, "thomas") < 0) { printf("failed.\n"); }
	sc_dump(id);
	
	printf("test: %s\n", sc_join(id));
	
	sc_clear(id);
	sc_dump(id);
}


static void cache_test(void) {
	struct df_cacheteststruct **ret;
	struct df_cacheteststruct *val;
	
	ret = malloc(sizeof(struct df_cacheteststruct *));
	
	val = malloc(sizeof(struct df_cacheteststruct));
	val->value = "ham";
	val->ivalue = 46;
	
	// store a bunch of stuff in the cache
	dfregexcache_cache("oranges", val);
	dfregexcache_cache("pears", val);
	dfregexcache_cache("bananas", val);
	dfregexcache_cache("strawberrys", val);
	dfregexcache_cache("rasberrys", val);
	dfregexcache_cache("peaches", val);
	
	dfregexcache_dump();
	
	if (dfregexcache_get("oranges", (void**)ret) == DFREGEXCACHE_ENOTFOUND) {
		printf("oranges not found in cache\n");
	}
	else { printf("oranges found in cache. v: %s  iv: %d\n", (*ret)->value, (*ret)->ivalue); }
	
	if (dfregexcache_get("pears", (void**)ret) == DFREGEXCACHE_ENOTFOUND) {
		printf("pears not found in cache\n");
	}
	else { printf("pears found in cache. v: %s  iv: %d\n", (*ret)->value, (*ret)->ivalue); }
	
	if (dfregexcache_get("bananas", (void**)ret) == DFREGEXCACHE_ENOTFOUND) {
		printf("bananas not found in cache\n");
	}
	else { printf("bananas found in cache. v: %s  iv: %d\n", (*ret)->value, (*ret)->ivalue); }
	
	if (dfregexcache_get("strawberrys", (void**)ret) == DFREGEXCACHE_ENOTFOUND) {
		printf("strawberrys not found in cache\n");
	}
	else { printf("strawberrys found in cache. v: %s  iv: %d\n", (*ret)->value, (*ret)->ivalue); }
	
	if (dfregexcache_get("rasberrys", (void**)ret) == DFREGEXCACHE_ENOTFOUND) {
		printf("rasberrys not found in cache\n");
	}
	else { printf("rasberrys found in cache. v: %s  iv: %d\n", (*ret)->value, (*ret)->ivalue); }
	
	if (dfregexcache_get("peaches", (void**)ret) == DFREGEXCACHE_ENOTFOUND) {
		printf("peaches not found in cache\n");
	}
	else { printf("peaches found in cache. v: %s  iv: %d\n", (*ret)->value, (*ret)->ivalue); }
	
	
	dfregexcache_free();
	
	dfregexcache_dump();
}



#define RUN_TIMES 1000
#define SLEEP_TIME 1

static void thread_test(void) {
	int i,r;
	
	dferrors_printdebug("Starting test.");
	
	// mad next
	for (i=0; i<RUN_TIMES; i++) {
		dferrors_printdebug(".");
		dfvoid_next(room_id);
		sleep(SLEEP_TIME);
	}
	
	// mad prev
	for (i=0; i<RUN_TIMES; i++) {
		dferrors_printdebug(".");
		dfvoid_previous(room_id);
		sleep(SLEEP_TIME);
	}
	
	// mad play/pause
	for (i=0; i<RUN_TIMES; i++) {
		dferrors_printdebug(".");
		dfvoid_pause(room_id);
		dfvoid_play(room_id);
		sleep(SLEEP_TIME);
	}
	
	for (i=0; i<RUN_TIMES; i++) {
		dferrors_printdebug(".");
		
		r = (int)(((double)rand()/(double)RAND_MAX) * 100);
		
		if (r>=0 && r<10) { 
			dfset_volume(room_id, 0);
			dfvoid_next(room_id);
			dfvoid_pause(room_id);
			dfvoid_play(room_id);
			dfset_volume(room_id, 255);
		}
		else if (r>=0 && r<10) {
			dfvoid_previous(room_id);
			dfset_shuffle(room_id, 0);
			dfvoid_previous(room_id);
			dfvoid_next(room_id);
			dfset_shuffle(room_id, 1);
		}
		else if (r>=10 && r<20) {
			dfset_repeat(room_id, 0);
			dfset_repeat(room_id, 1);
			dfvoid_next(room_id);
			dfvoid_next(room_id);
			dfvoid_next(room_id);
		}
		else if (r>=20 && r<30) {
			dfvoid_pause(room_id);
			dfvoid_next(room_id);
			dfvoid_play(room_id);
		}
		else if (r>=40 && r<50) {
			dfvoid_pause(room_id);
			dfvoid_previous(room_id);
			dfvoid_play(room_id);
		}
		else if (r>=50 && r<100) {
			dfget_volume(room_id, print_int);
			dfget_playerstatus(room_id, print_string);
			dfget_repeat(room_id, print_int);
			dfget_shuffle(room_id, print_int);
			dfget_trackname(room_id, print_gettrackname);
			dfget_tracknum(room_id, print_int);
			dfget_trackpos(room_id, print_time);
			dfget_albumartist(room_id, print_albumartist);
		}
		
		sleep(SLEEP_TIME);
	}
	
	dferrors_printdebug("Done.\n");
}


static void stringext_test(void) {
	char *in;
	char *out;
	
	in = malloc(sizeof(char) * 14);
	strcpy(in, "1111222221111");
	
	string_extract(&in, &out, 4, 5);
	
	printf("in: %s   out: %s", in, out);
	
	free(out);
	free(in);
}


static void print_gettrackname(df_track *tr) {
	printf("Key: %d\n", tr->key);
	printf("Name: %s\n", tr->name);
	printf("Type: %s\n", tr->type);
	printf("Length: %dh %dm %ds\n", tr->length->hours, tr->length->minutes, tr->length->seconds);
	printf("Source: %d\n", tr->source);
}

static void print_albumartist(df_albumartist *aa) {
	printf("Artist: %s\n", aa->artist);
	printf("Album: %s\n", aa->album);
}

static void print_time(df_time *t) {
	printf("Time: %dh %dm %ds\n", t->hours, t->minutes, t->seconds);
}

static void print_int(int i) {
	printf("Val: %d\n", i);
}

static void print_string(char *s) {
	printf("Val: %s\n", s);
}


static void print_trackname(df_trackname *tn) {
	printf("Name: %s\n", tn->name);
	printf("Source: %d\n", tn->source);
	printf("Path: %s\n", tn->path);
}

static void print_detailedtrack(df_detailedtrack *dt) {
	printf("Key: %d\n", dt->key);
	printf("Name: %s\n", dt->name);
	printf("Album Key: %d\n", dt->albumkey);
	printf("Album Name: %s\n", dt->albumname);
	printf("Artist Key: %d\n", dt->artistkey);
	printf("Artist Name: %s\n", dt->artistname);
	printf("Genre Key: %d\n", dt->genrekey);
	printf("Genre Name: %s\n", dt->genrename);
	printf("Length: %dh %dm %ds\n", dt->length->hours, dt->length->minutes, dt->length->seconds);
	printf("Source: %d\n", dt->source);
	printf("Path: %s\n", dt->path);
}

static void print_checkcoverimage(char *name, char *uri) {
	printf("Name: %s\n", name);
	printf("URI: %s\n", uri);
}


static void print_artistrow(df_rows *info, df_artistrow *ar) {
	df_artistrow *current;
	
	current = ar;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("Key: %d   Name: %s\n", current->key, current->name);
		
		current = current->next;
	}
}

static void print_roomrow(df_rows *info, df_roomrow *rr) {
	df_roomrow *current;
	
	current = rr;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("Key: %d   Name: %s   Id: %d\n", current->key, current->name, current->id);
		
		current = current->next;
	}
}


static void print_albumrow(df_rows *info, df_albumrow *ar) {
	df_albumrow *current;
	
	current = ar;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("[%d]\t%s - %s\n", current->key, current->artist_name, current->name);
		
		current = current->next;
	}
}


static void print_albumdetailrow(df_rows *info, df_albumdetailrow *ar) {
	df_albumdetailrow *current;
	
	current = ar;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("[%d]\t%s - %s   (%s)\n", current->key, current->artist_name, current->name, current->cover_image);
		
		current = current->next;
	}
}


static void print_trackrow(df_rows *info, df_trackrow *tr) {
	df_trackrow *current;
	
	current = tr;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("[%d]\t%s\n", current->key, current->name);
		
		current = current->next;
	}
}


static void print_genrerow(df_rows *info, df_genrerow *gr) {
	df_genrerow *current;
	
	current = gr;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("[%d]\t%s\n", current->key, current->name);
		
		current = current->next;
	}
}


static void print_subgenrerow(df_rows *info, df_subgenrerow *sgr) {
	df_subgenrerow *current;
	
	current = sgr;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("[%d]\t%s\n", current->key, current->name);
		
		current = current->next;
	}
}


static void print_keyvaluerow(df_rows *info, df_keyvaluerow *kvr) {
	df_keyvaluerow *current;
	
	current = kvr;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("%s = %s\n", current->key, current->value);
		
		current = current->next;
	}
}


static void print_trackinforow(df_rows *info, df_trackinforow  *tir) {
	df_trackinforow  *current;
	
	current = tir;
	
	printf("Total rows: %d\n", info->count);
	
	while (current!=NULL) {
		printf("[%d]\t%s>%s>%s\n", current->key, current->artist_name, current->album_name, current->sort_name);
		
		current = current->next;
	}
}












static void error_callback(int num, char *message) {
	printf("Error [%d]: %s", num, message);
	fflush(stdout);
}
static void debug_callback(char *message) {
	printf("%s", message);
	fflush(stdout);
}


static void connect_callback(int err) {
	printf((err==0) ? "Connected" : "Failed to connect.");
}

static void discover_callback(df_server *servers) {
	df_server *current;
	
	if (servers!=NULL) {
		printf("Avaliable Servers\n-------------------------\n");
		current = servers;
		while (current!=NULL) {
			printf("%s\t%s\t%s\n", current->name, current->version, current->address);
			
			current = current->next;
		}
	}
	else {
		printf("got no servers :(\n");
	}
}


